#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>


template<typename T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }
public:
    RingQueue(int cap = 8) 
        : _cap(cap) 
        , _ring_queue(_cap)
        , _productor_step(0)
        , _consumer_step(0)
    {
        sem_init(&_room_sem,0,_cap);
        sem_init(&_data_sem,0,0);
    }
    
    void Enqueue(const T &in) // 生产
    {
        P(_room_sem);
        // 一定有空间
        _ring_queue[_productor_step++] = in;
        _productor_step %= _cap;
        V(_data_sem);
    }
    void Pop(T *out) // 消费
    {
        P(_data_sem);
        *out = _ring_queue[_consumer_step++];
        _consumer_step %= _cap;
        V(_room_sem);
    }

    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);
    }
private:
    // 1. 环形队列
    int _cap; // 环形队列容量
    std::vector<T> _ring_queue;

    // 2. 生产者和消费者的下标
    int _productor_step;
    int _consumer_step;

    // 3. 定义信号量
    sem_t _room_sem;    // 生产者关心
    sem_t _data_sem;    // 消费者关心
};